package com.prj.ufdm.cloud.ms.core.util;

import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;

/**
 * DESC: RestTemplate 工具类 <br>
 * @author 胡义振
 * @date 2020年2月26日
 */
public class CoreRestTemplateUtil {

	private static final Log log = LogFactory.getLog(CoreRestTemplateUtil.class);
	
	RestTemplate restTmpl;
	
	public CoreRestTemplateUtil(){
		this.restTmpl = new RestTemplate();
	}
	
	public CoreRestTemplateUtil(RestTemplate restTemplate){
		this.restTmpl = restTemplate;
	}

	/**
	 * DESC: POST 表单提交 
	 * @auther 胡义振
	 * @date 2020年3月2日
	 * @param reqUrl     请求URL地址
	 * @param reqHeadParamMap  head 参数
	 * @param reqFormParamMap  form 参数
	 * @param typeReference    返回的数据类型，如果为NULL，返回 String 类型
	 * @throws Exception 
	 * @return
	 */
	public <T> T reqPostForm(String reqUrl, Map<String,String> reqHeadParamMap, Map<String,String> reqFormParamMap,TypeReference<T> typeReference)  throws Exception 
	{
		/** 设置头信息 */
		HttpHeaders headers = wrapToHttpHead(reqHeadParamMap);
		headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
		/** 设置参数信息 */
		MultiValueMap<String, String> postParam = wrapToMultiMap(reqFormParamMap);
		/** 设置请求消息体 */
	    HttpEntity<MultiValueMap<String, String>> reqHttpEntity = new HttpEntity<MultiValueMap<String, String>>(postParam, headers);
	    /** 发送HTTP请求 */
		ResponseEntity<String> resResult = this.restTmpl.exchange(reqUrl, HttpMethod.POST, reqHttpEntity, String.class);
		System.out.println("\n resResult:"+resResult.getBody());
		return getReturnObject(resResult,typeReference);
	}
	
	/**
	 * DESC: GET 请求
	 * @auther 胡义振
	 * @date 2020年3月2日
	 * @param reqUrl     请求URL地址
	 * @param reqHeadParamMap  head 参数
	 * @param queryParamMap  查询参数
	 * @param typeReference    返回的数据类型，如果为NULL，返回 String 类型
	 * @throws Exception 
	 * @return
	 */
	public <T> T reqGetParam(String reqUrl, Map<String,String> reqHeadParamMap, Map<String,String> queryParamMap, TypeReference<T> typeReference)  throws Exception 
	{
		/** 设置头信息 */
		HttpHeaders headers = wrapToHttpHead(reqHeadParamMap);
		headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
		/** 设置参数信息 */
		String queryParam = mapToUrlParam(queryParamMap);
		String reqUri = reqUrl.concat("?").concat(queryParam);
		/** 设置请求消息体 */
		HttpEntity<String> reqHttpEntity = new HttpEntity<String>(headers);
		/** 发送HTTP请求 */
		ResponseEntity<String> resResult = this.restTmpl.exchange(reqUri, HttpMethod.GET, reqHttpEntity, String.class);
		System.out.println("\n resResult:"+resResult.getBody());
		return getReturnObject(resResult,typeReference);
	}
	
	/**
	 * DESC: POST JSON 提交 
	 * @auther 胡义振
	 * @date 2020年3月2日
	 * @param reqUrl     请求URL地址
	 * @param reqHeadParamMap  head 参数
	 * @param reqFormParamMap  form 参数
	 * @param typeReference    返回的数据类型，如果为NULL，返回 String 类型
	 * @throws Exception 
	 * @return
	 */
	public <T> T reqPostJson(String reqUrl, Map<String,String> reqHeadParamMap, Map<String,String> reqFormParamMap,TypeReference<T> typeReference)  throws Exception 
	{
		/** 设置头信息 */
		HttpHeaders headers = wrapToHttpHead(reqHeadParamMap);
		headers.setContentType(MediaType.parseMediaType(MediaType.APPLICATION_JSON+";charset=utf-8"));
		headers.add("Accept", "application/json;charset=utf-8");
		/** 设置参数信息 */
		MultiValueMap<String, String> postParam = wrapToMultiMap(reqFormParamMap);
		/** 设置请求消息体 */
	    HttpEntity<MultiValueMap<String, String>> reqHttpEntity = new HttpEntity<MultiValueMap<String, String>>(postParam, headers);
	    /** 发送HTTP请求 */
		ResponseEntity<String> resResult = this.restTmpl.exchange(reqUrl, HttpMethod.POST, reqHttpEntity, String.class);
		System.out.println("\n resResult:"+resResult.getBody());
		return getReturnObject(resResult,typeReference);
	}
	
	
	/**
	 * DESC: JSON 转为对象
	 * @auther 胡义振
	 * @date 2020年3月2日
	 * @param resResult
	 * @param typeReference
	 * @return 
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private static <T> T getReturnObject(ResponseEntity<String> resResult,TypeReference<T> typeReference) {
		T returnObj = null;
		if(typeReference!=null) {
			returnObj = JSON.parseObject(resResult.getBody(), typeReference);
		}
		else {
			returnObj = (T) resResult.getBody();
		}
		return returnObj;
	}
	
	
	/**
	 * DESC: headMap 转为 HttpHeaders
	 * @auther 胡义振
	 * @date 2020年3月2日
	 * @param headMap
	 * @return
	 */
	private static HttpHeaders wrapToHttpHead(Map<String,String> headMap) {
    	HttpHeaders header = new HttpHeaders();
		if(headMap!=null) {
			Set<String> headKey = headMap.keySet();
			Iterator<String> headIt = headKey.iterator();
			while(headIt.hasNext()){
				String tempKey = headIt.next();
				String tempValue = headMap.get(tempKey)!=null ? headMap.get(tempKey) : "";
				header.add(tempKey,tempValue);
			}
		}
		return header;
    }
    
	/**
	 * DESC: 参数 Map 转为 MultiValueMap
	 * @auther 胡义振
	 * @date 2020年3月2日
	 * @param headMap
	 * @return
	 */
	private static MultiValueMap<String, String> wrapToMultiMap(Map<String,String> paramMap) {
		MultiValueMap<String, String> paramMultiMap = new LinkedMultiValueMap<String, String>();
		if(paramMap!=null) {
			Set<String> headKey = paramMap.keySet();
			Iterator<String> headIt = headKey.iterator();
			while(headIt.hasNext()){
				String tempKey = headIt.next();
				String tempValue = paramMap.get(tempKey)!=null ? paramMap.get(tempKey) : "";
				paramMultiMap.add(tempKey,tempValue);
			}
		}
		return paramMultiMap;
    }
    
    /**
     * DESC: 把Map转成URL参数
     * @auther 胡义振
     * @date 2020年3月2日
     * @param reqParamMap
     * @param encode
     * @return
     * @throws Exception 
     * @return
     */
	private static String mapToUrlParam(Map<String,String> reqParamMap) throws Exception{
		String params = "";
		if(reqParamMap!=null) {
			String tempKey;
			String tempValue;
			Set<String> paramKey = reqParamMap.keySet();
			Iterator<String> it = paramKey.iterator();
			while(it.hasNext()){
				tempKey = it.next();
				tempValue = reqParamMap.get(tempKey)!=null ? reqParamMap.get(tempKey) : "";
				if(params.equals("")){
					params = tempKey + "=" + tempValue;
				}
				else{
					params = params + "&" + tempKey + "=" + tempValue;
				}
			}
		}
		return params;
	}

}
